package com.jvyou.common.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.jvyou.common.response.BizResponseCode;
import com.jvyou.common.response.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.BindingException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 异常处理
 *
 * @author dhb
 */
@RestControllerAdvice
@Slf4j
public class ExceptionHandlerConfigure {

    /**
     * 处理在没有登录请求的异常
     *
     * @param exception NotLoginException
     * @return 返回401的http状态码
     */
    @ResponseBody
    @ExceptionHandler
    public ResponseEntity<R<String>> handle(NotLoginException exception) {
        log.debug("", exception);
        R<String> r = new R<>();
        r.setCode(HttpStatus.UNAUTHORIZED.value());
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(r);
    }

    /**
     * 处理业务异常
     *
     * @param exception BizException
     * @return 返回200的http状态码，body描述异常信息
     */
    @ResponseBody
    @ExceptionHandler
    public R<Object> handle(BizException exception) {
        return R.build(exception);
    }

    /**
     * 处理参数错误的异常
     *
     * @param exception BadRequestException
     * @return 返回400状态码
     */
    @ResponseBody
    @ExceptionHandler
    public ResponseEntity<R<String>> handle(BadRequestException exception) {
        R<String> r = new R<>();
        r.setMessage(exception.getMessage()).setData(null).setCode(HttpStatus.BAD_REQUEST.value());

        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(r);
    }


    /**
     * 处理角色无权操作异常
     *
     * @param exception ex
     * @return r
     */
    @ResponseBody
    @ExceptionHandler
    public R<String> handle(NotRoleException exception) {
        log.debug("当前用户角色无权操作", exception);
        BizResponseCode code = BizResponseCode.ERR_11003;
        R<String> r = new R<>();
        r.setMessage(code.getMsg())
                .setCode(code.getCode());
        return r;
    }

    /**
     * 处理参数错误异常
     *
     * @param exception ex
     * @return r
     */
    @ResponseBody
    @ExceptionHandler
    public R<String> handle(MethodArgumentNotValidException exception) {
        ObjectError error = exception.getBindingResult().getAllErrors().getFirst();
        String defaultMessage = error.getDefaultMessage();
        return R.build(new BizException(BizResponseCode.ERR_400, defaultMessage));
    }


    /**
     * 数据库语句错误
     */
    @ExceptionHandler(BadSqlGrammarException.class)
    public R<String> sqlException(Exception e) {
        String message = e.getMessage();
        String[] split = message.split("###");
        split = split[2].replace("]", "").split("\\\\");
        String xml = split[split.length - 1].replace("\n", "");
        String sql = message.split("### Cause: ")[0].split("### SQL: ")[1].replace("\n", "");
        while (sql.contains("  ")) {
            sql = sql.replace("  ", " ");
        }
        log.error("==========================");
        log.error("SQL语句发生错误");
        log.error("xml: {}", xml);
        log.error("sql：{}", sql);
        log.error("==========================");
        return R.build(new BizException(BizResponseCode.ERR_500, "数据库语句错误"));
    }

    /**
     * 数据库语句错误
     */
    @ExceptionHandler({SQLException.class, BindingException.class})
    public R<String> handleSQLException(Exception e) {
        String message = e.getMessage();
        log.error("数据库语句错误，异常信息:", e);
        if (message.contains("Duplicate entry")) {
            Pattern pattern = Pattern.compile("'([^']+)'");
            Matcher matcher = pattern.matcher(message);
            String data = matcher.find() ? matcher.group(1) : "-";
            message = "已存在该数据（" + data + "），请修改后重试！";
            return R.build(new BizException(BizResponseCode.ERR_500, message));
        } else if (message.contains("Data too long")) {
            message = "数据长度过长，请修改后重试！";
            return R.build(new BizException(BizResponseCode.ERR_500, message));
        } else if (message.contains("doesn't have a default value")) {
            Pattern pattern = Pattern.compile("'([^']+)'");
            Matcher matcher = pattern.matcher(message);
            String field = matcher.find() ? matcher.group(1) : "-";
            message = field + " 数据不能为空，请修改后重试！";
        }
        return R.build(new BizException(BizResponseCode.ERR_500, message));
    }

    /**
     * 无权限
     *
     * @return 响应结果
     */
    @ExceptionHandler(NotPermissionException.class)
    public R<Boolean> handlerNotPermissionException(NotPermissionException notLoginException) {
        return R.build(new BizException(BizResponseCode.ERR_11003));
    }

}
